package com.ccl.iot.managers;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.ccl.iot.EIOT_RESULT;
import com.ccl.iot.IOTCallback;
import com.ccl.iot.IOTDataType.IOTInt;
import com.ccl.iot.IOTListScanner;
import com.ccl.iot.IOTNetAPI;
import com.ccl.iot.IOTNetAPIEnum;
import com.ccl.iot.IOTObject.IOTScannableObject.IOTScanListener;
import com.ccl.iot.IOTScanner;
import com.ccl.iot.db.SqlOpenHelper;
import com.ccl.iot.object.IOTAuthInfo;
import com.ccl.iot.privates.ListMap;

import java.util.ArrayList;
import java.util.List;

public class AuthManager extends Manager {
    private static AuthManager gDefault = null;

    public static final String DB_NAME = "cache.db";
    private static final String AUTHUSER_TABLE_NAME = "authuser";
    private static final String AUTHDEV_TABLE_NAME = "authdev";
    private final static String DEV_TABLE_SQL = " (_id integer primary key autoincrement, devid int, authid int, version int)";
    private final static String USER_TABLE_SQL = " (curid int, nextid int, devid int, userid int, authid int, username text, version int)";
    private SQLiteDatabase mAuthUserDb;
    private SQLiteDatabase mAuthDevDb;
    private boolean mFromAuthDevDB, mFromAuthUserDB;

    public static AuthManager GetDefaultManager(Context aContext) {
        if (gDefault == null) {
            gDefault = new AuthManager(aContext);
        }

        return gDefault;
    }

    public static AuthManager GetDefaultManager() {
        return gDefault;
    }

    private UserManager iUserManager = null;
    private IOTNetAPI iNetAPI = null;
    private long iAuthDevicesUser = 0;
    private ListMap<Long, IOTAuthInfo> iAuthDevices = null;
    private IOTListScanner<IOTAuthInfo> iAuthDevicesScanner = new IOTListScanner<IOTAuthInfo>(null);
    private long iAuthUsersDevice = 0;
    private ListMap<Long, IOTAuthInfo> iAuthUsers = null;
    private IOTScanner<IOTAuthInfo> iAuthUsersScanner = new IOTScanner<IOTAuthInfo>(null);

    private int iDevLastVersion = -1;
    private int iDevTmpVersion = 0;
    private int iUserLastVersion = -1;
    private int iUserTmpVersion = 0;

    private AuthManager(Context aContext) {
        super(aContext);
        onCreate();
    }

    @Override
    public boolean filteError(int aError) {
        if (aError == EIOT_RESULT.EIOT_RESULT_GENERAL_NO_AUTHORIZE_DEVICE || aError == EIOT_RESULT.EIOT_RESULT_GENERAL_NO_AUTHORIZE_USER) {
            return true;
        }

        return false;
    }

    private void onCreate() {
        super.create();

        iNetAPI = IOTNetAPI.GetInstance();
        if (iNetAPI != null) {
            iAuthDevicesUser = iNetAPI.getLogonUser();
            iNetAPI.setAuthStateCallback(iAuthStateCallback);
        }

        //==========modify start================
        iUserManager = UserManager.GetDefaultManager();
        iUserManager.addUserEventListener(iLoginListener);
        //==========modify end================
    }

    @Override
    public void onSuspend() {
        super.onSuspend();

        iAuthDevicesScanner.stopScan();
        iAuthUsersScanner.stopScan();
    }

    private IOTCallback.AuthStateCallback iAuthStateCallbackEx = null;

    public void setAuthStateCallback(IOTCallback.AuthStateCallback aCallback) {
        iAuthStateCallbackEx = aCallback;
    }

    private IOTCallback.AuthStateCallback iAuthStateCallback = new IOTCallback.AuthStateCallback() {
        @Override
        public void onAuthStateCallback(int aNetWork, long aDevID, int aNewAuth) {
            if (iAuthDevices != null) {
                IOTAuthInfo tInfo = iAuthDevices.getValue(aDevID);
                if (tInfo != null) {
                    if (tInfo.iAuthState != aNewAuth) {
                        tInfo.iAuthState = aNewAuth;
                    } else {
                        return;
                    }
                }
            }

            if (iAuthStateCallbackEx != null) {
                iAuthStateCallbackEx.onAuthStateCallback(aNetWork, aDevID, aNewAuth);
            }
        }
    };

    public int getAuthDevicesCount() {
        return iNetAPI.getAuthDeviceCount();
    }

    public boolean startScanAuthDevices(IOTScanListener<IOTAuthInfo> aListener) {
        final IOTAuthInfo tInfo = new IOTAuthInfo();

        if (iAuthDevices == null) {
            iAuthDevices = new ListMap<Long, IOTAuthInfo>();
        }
        //根据版本判断数据是否有改变
        iDevTmpVersion = iNetAPI.getAuthDeviceVersion();
        //当数据有变化时重新获取数据

        if (iDevTmpVersion != iDevLastVersion) {
            mFromAuthDevDB = false;
            if(!iUserManager.isLogon()){
                mFromAuthDevDB = true;
            }else if (mAuthDevDb != null && mAuthDevDb.isOpen()) {
                Cursor query = mAuthDevDb.query(AUTHDEV_TABLE_NAME, new String[]{"version"}, null, null, null, null, null);
                if (query != null) {
                    if (query.moveToNext()) {
                        mFromAuthDevDB = iDevTmpVersion == query.getInt(0);
                    }
                    query.close();
                }
            }

            iAuthDevices.clear();

            return iAuthDevicesScanner.startScan(new IOTListScanner.ScanImpl<IOTAuthInfo>() {
                int count = 0;

                private IOTAuthInfo newInfo(IOTAuthInfo aInfo) {
                    //                    IOTAuthInfo tClone = aInfo.clone();

                    if (iAuthDevices.add(aInfo.iAuthObject, aInfo)) {
                        count++;
                        return aInfo;
                    } else {
                        return null;
                    }
                }

                /*@Override
                public IOTAuthInfo scanFirst() {
                    if (iNetAPI.getAuthDeviceFirst(tInfo) == 0) {
                        return newInfo(tInfo);
                    } else {
                        return null;
                    }
                }

                @Override
                public IOTAuthInfo scanNext() {
                    if ((result = iNetAPI.getAuthDeviceNext(tInfo)) == 0) {
                        return newInfo(tInfo);
                    } else {
                        return null;
                    }
                }*/

                @Override
                public void scanStart() {
                }

                @Override
                public List<IOTAuthInfo> scanDevices() {
                    ArrayList<IOTAuthInfo> authDeviceList = null;
                    if (mFromAuthDevDB && mAuthDevDb != null && mAuthDevDb.isOpen()) {
                        Cursor query = mAuthDevDb.query(AUTHDEV_TABLE_NAME, new String[]{"devid", "authid"}, null, null, null, null, null);
                        if (query != null) {
                            authDeviceList = new ArrayList<IOTAuthInfo>();
                            while (query.moveToNext()) {
                                authDeviceList.add(new IOTAuthInfo(0, query.getInt(0), query.getInt(1)));
                            }
                            query.close();
                        }
                    }

                    if (!mFromAuthDevDB || authDeviceList == null || authDeviceList.size() <= 0) {
                        authDeviceList = iNetAPI.getAuthDeviceList();
                        if (mAuthDevDb != null && mAuthDevDb.isOpen()) {
                            mAuthDevDb.delete(AUTHDEV_TABLE_NAME, null, null);
                            if (authDeviceList != null && authDeviceList.size() > 0) {
                                ContentValues cv = new ContentValues();
                                for (int i = 0; i < authDeviceList.size(); i++) {
                                    IOTAuthInfo iotAuthInfo = authDeviceList.get(i);
                                    if (iotAuthInfo != null) {
                                        cv.put("devid", iotAuthInfo.iAuthObject);
                                        cv.put("authid", iotAuthInfo.iAuthState);
                                        mAuthDevDb.insert(AUTHDEV_TABLE_NAME, null, cv);
                                    }
                                }
                                cv.clear();
                                cv.put("version", iDevTmpVersion);
                                mAuthDevDb.update(AUTHDEV_TABLE_NAME, cv, "_id=?", new String[]{"0"});
                            }
                        }
                    }

                    if (authDeviceList != null && authDeviceList.size() > 0) {
                        ArrayList<IOTAuthInfo> realList = new ArrayList<IOTAuthInfo>();
                        for (IOTAuthInfo info : authDeviceList) {
                            IOTAuthInfo realinfo;
                            if ((realinfo = newInfo(info)) != null) {
                                realList.add(realinfo);
                            }
                        }

                        if (realList.size() > 0) {
                            return realList;
                        }
                    }
                    return null;
                }

                @Override
                public void scanDone() {
                    if (count == getAuthDevicesCount()) {
                        iDevLastVersion = iDevTmpVersion;
                    }
                    count = 0;
                }
            }, aListener);
        } else {
            //当数据无变化则不用重新获取
            if (iAuthDevices != null && iAuthDevices.size() > 0 && aListener != null) {
                ArrayList<IOTAuthInfo> values = iAuthDevices.getValues();
                for (IOTAuthInfo iotAuthInfo : values) {
                    aListener.onScanResult(null, iotAuthInfo);
                }
            }
            return true;
        }

    }

    public void stopScanAuthDevices() {
        iAuthDevicesScanner.stopScan();
    }

    public boolean isDeviceAuthStateCached(long aDevID) {
        if (iAuthDevicesUser != iNetAPI.getLogonUser() || iAuthDevices == null || iAuthDevices.size() == 0) {
            return false;
        } else if (iAuthDevices != null) {
            return iAuthDevices.getValue(aDevID) != null;
        }

        return false;
    }

    public int getDeviceAuthState(long aDevID, boolean aRealState) {
        boolean tOld = false;

        if (iAuthDevicesUser != iNetAPI.getLogonUser()) {
            if (iAuthDevices != null && iAuthDevices.size() > 0) {
                iAuthDevices.clear();
            }
            tOld = true;
        }

        if (tOld || aRealState || iAuthDevices == null || iAuthDevices.size() == 0) {
            IOTInt tAuthState = new IOTInt();

            if (iNetAPI.authCheck(aDevID, tAuthState)) {
                iAuthStateCallback.onAuthStateCallback(iNetAPI.isRemoteReady() ? IOTNetAPIEnum.EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_REMOTE : IOTNetAPIEnum.EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_LOCAL,
                        aDevID, tAuthState.getValue());

                return tAuthState.getValue();
            }
        } else if (iAuthDevices != null) {
            IOTAuthInfo tInfo = iAuthDevices.getValue(aDevID);

            if (tInfo != null) {
                return tInfo.iAuthState;
            }
        }

        return IOTNetAPIEnum.EAUTH_STATE.EAUTH_STATE_UNKNOWN;
    }

    public int getAuthUsersCount(long aDevID) {
        return iNetAPI.getAuthUserCount(aDevID);
    }

    public boolean startScanAuthUsers(long aDevID, final IOTScanListener<IOTAuthInfo> aListener) {
        final long tDevID = aDevID;
        final IOTAuthInfo tInfo = new IOTAuthInfo();

        if (iAuthUsers == null) {
            iAuthUsers = new ListMap<Long, IOTAuthInfo>();
        }

        //根据版本判断数据是否有改变
        iUserTmpVersion = iNetAPI.getAuthUserVersion(aDevID);
        //当数据有变化时重新获取数据
        if (iUserTmpVersion != iUserLastVersion) {
            mFromAuthUserDB = false;
            if (mAuthUserDb != null && mAuthUserDb.isOpen()) {
                Cursor query = mAuthUserDb.query(AUTHUSER_TABLE_NAME, new String[]{"version"}, "curid=? and devid=?", new String[]{"0", tDevID + ""}, null, null, null);
                if (query != null) {
                    if (query.moveToNext()) {
                        mFromAuthUserDB = iUserTmpVersion == query.getInt(0);
                    }
                    query.close();
                }
            }

            iAuthUsers.clear();
            iAuthUsersDevice = aDevID;

            final ContentValues cv = new ContentValues();
            return iAuthUsersScanner.startScan(new IOTScanner.ScanImpl<IOTAuthInfo>() {
                int result = 0;

                private IOTAuthInfo newInfo(IOTAuthInfo aInfo) {
                    IOTAuthInfo tClone = aInfo.clone();

                    if (iAuthUsers.add(aInfo.iAuthObject, tClone)) {
                        return tClone;
                    } else {
                        return null;
                    }
                }

                @Override
                public IOTAuthInfo scanFirst() {
                    if (mFromAuthUserDB) {
                        if (mAuthUserDb != null && mAuthUserDb.isOpen()) {
                            Cursor query = mAuthDevDb.query(AUTHUSER_TABLE_NAME, new String[]{"nextid", "userid", "authid"}, "curid=? and devid=?", new String[]{"0", tDevID + ""}, null, null, null);
                            if (query != null) {
                                if (query.moveToNext()) {
                                    tInfo.iID = query.getInt(0);
                                    tInfo.iAuthObject = query.getInt(1);
                                    tInfo.iAuthState = query.getInt(2);
                                    return newInfo(tInfo);
                                }
                                query.close();
                            }
                        }
                    }
                    if ((result = iNetAPI.getAuthUserFirst(tDevID, tInfo)) == 0) {
                        if (mAuthUserDb != null && mAuthUserDb.isOpen()) {
                            cv.clear();
                            //                            (curid int, nextid int, devid int, userid int, authid int, username text, version int)
                            cv.put("curid", 0);
                            cv.put("nextid", tInfo.iID);
                            cv.put("devid", tDevID);
                            cv.put("userid", tInfo.iAuthObject);
                            cv.put("authid", tInfo.iAuthState);
                            cv.put("version", iUserTmpVersion);
                            mAuthUserDb.insert(AUTHUSER_TABLE_NAME, null, cv);
                        }
                        return newInfo(tInfo);
                    } else {
                        return null;
                    }
                }

                @Override
                public IOTAuthInfo scanNext() {
                    if (mFromAuthUserDB) {
                        if (mAuthUserDb != null && mAuthUserDb.isOpen()) {
                            Cursor query = mAuthDevDb.query(AUTHUSER_TABLE_NAME, new String[]{"nextid", "userid", "authid"}, "curid=? and devid=?", new String[]{"0", tDevID + ""}, null, null, null);
                            if (query != null) {
                                if (query.moveToNext()) {
                                    tInfo.iID = query.getInt(0);
                                    tInfo.iAuthObject = query.getInt(1);
                                    tInfo.iAuthState = query.getInt(2);
                                    return newInfo(tInfo);
                                }
                                query.close();
                            }
                        }
                    }
                    long curid = tInfo.iID;
                    if ((result = iNetAPI.getAuthUserNext(tDevID, tInfo)) == 0) {
                        if (mAuthUserDb != null && mAuthUserDb.isOpen()) {
                            //                            (curid int, nextid int, devid int, userid int, authid int, username text, version int)
                            cv.clear();
                            cv.put("curid", curid);
                            cv.put("nextid", tInfo.iID);
                            cv.put("devid", tDevID);
                            cv.put("userid", tInfo.iAuthObject);
                            cv.put("authid", tInfo.iAuthState);
                            mAuthUserDb.insert(AUTHUSER_TABLE_NAME, null, cv);
                        }
                        return newInfo(tInfo);
                    } else {
                        return null;
                    }
                }

                @Override
                public void scanStart() {
                }

                @Override
                public void scanDone() {
                    if (result == EIOT_RESULT.EIOT_RESULT_GENERAL_NO_AUTHORIZE_USER) {
                        iDevLastVersion = iDevTmpVersion;
                    }
                }
            }, aListener);
        } else {
            //当数据无变化则不用重新获取
            if (iAuthUsers != null && iAuthUsers.size() > 0 && aListener != null) {
                ArrayList<IOTAuthInfo> values = iAuthUsers.getValues();
                for (IOTAuthInfo iotAuthInfo : values) {
                    aListener.onScanResult(null, iotAuthInfo);
                }
            }
            return true;
        }

    }

    public void stopScanAuthUsers() {
        iAuthUsersScanner.stopScan();
    }

    public int getUserAuthState(long aDevID, long aUser) {
        if (aDevID != iAuthUsersDevice || iAuthUsers == null || iAuthUsers.size() == 0) {
            startScanAuthUsers(aDevID, null);
        }

        if (iAuthUsers != null) {
            IOTAuthInfo tInfo = iAuthUsers.getValue(aUser);

            if (tInfo != null) {
                return tInfo.iAuthState;
            }
        }

        return IOTNetAPIEnum.EAUTH_STATE.EAUTH_STATE_UNKNOWN;
    }

    /**
     * 请求或者抛弃已有权限
     *
     * @param aDevID       设备id
     * @param aRequestQuit 请求或者抛弃权限	true: 抛弃权限,  false: 请求权限
     * @return
     */
    public boolean requestAuth(long aDevID, boolean aRequestQuit) {
        return iNetAPI.authRequest(aDevID, aRequestQuit);
    }

    public boolean requestUpdateAuth(long aDevID, long aUser, int aNewAuth, long aTimeout) {
        return iNetAPI.authUpdate(aNewAuth, aUser, aDevID, aTimeout);
    }

    //==========modify start================
    private UserManager.UserEventListener iLoginListener = new UserManager.UserEventListener() {

        private long mTUserID;

        @Override
        public void onLoginEvent(boolean aCanceled) {
            //增加数据库存储权限设备及权限用户信息
            iAuthDevicesUser = iNetAPI.getLogonUser();
            if (mTUserID != iAuthDevicesUser) {
                mTUserID = iAuthDevicesUser;
                if (mAuthUserDb != null && mAuthUserDb.isOpen()) {
                    mAuthUserDb.close();
                }
                mAuthUserDb = new SqlOpenHelper(Manager.DBCONTEXT, DB_NAME, AUTHUSER_TABLE_NAME, USER_TABLE_SQL).getWritableDatabase();
                if (mAuthDevDb != null && mAuthDevDb.isOpen()) {
                    mAuthDevDb.close();
                }
                mAuthDevDb = new SqlOpenHelper(Manager.DBCONTEXT, DB_NAME, AUTHDEV_TABLE_NAME, DEV_TABLE_SQL).getWritableDatabase();
            }
        }

        @Override
        public void onPrepareLogout() {
        }

        @Override
        public void onLogout(boolean aOK) {
            if (mAuthUserDb != null && mAuthUserDb.isOpen()) {
                mAuthUserDb.close();
            }
            mAuthUserDb = null;
            if (mAuthDevDb != null && mAuthDevDb.isOpen()) {
                mAuthDevDb.close();
            }
            mAuthDevDb = null;
        }
    };
    //==========modify start================

}
